﻿// -------------------------------------------------------------------------
//    @FileName         :    NFItemOperator.cpp
//    @Author           :    gaoyi
//    @Date             :    2024/12/20
//    @Email            :    445267987@qq.com
//    @Module           :    NFItemOperator
//
// -------------------------------------------------------------------------

// --- 文件总结 ---------------------------------------------------------------
// 本文件实现 NFBagPageOpMgr 类的功能：
// - 构造/析构：初始化玩家背包操作管理器和金钱操作器
// - Commit：提交所有背包和金钱变更，同步到客户端，触发事件
// - CommitToPlayer：预检查、提交金钱、提交背包页签、触发物品增删事件
// - SyncToPlayer：同步背包和金钱变更到客户端
// - PreCheckCommit：预检查提交前的状态
// - GetBagPage：获取指定类型的背包页签
// - AddAllBagPage：添加所有常用背包页签
// - GetMoneyNumber/SetMoneyNumber：获取/设置金钱数量
// - IncMoney/DecMoney：增加/减少金钱
// - AddItemWhenBagFull：背包满时的特殊处理（发送邮件）
// - SendRewardNtf：发送奖励通知
// - FillPackageInfoForAdd/Del：填充背包变更通知消息
// ---------------------------------------------------------------------------

#include "NFBagPageOpMgr.h"
#include <NFLogicCommon//BagPage/NFBagPageOp.h>
#include <NFPacketSendUtil.h>
#include <NFPlayer.h>
#include <NFServicePackage.h>

#include "NFLogicCommon/BagPage/NFBagDefine.h"
#include "NFPackagePart.h"
#include "proto_event.nanopb.h"
#include "proto_event.pb.h"
#include "NFComm/NFPluginModule/NFIEventModule.h"

NFBagPageOpMgr::NFBagPageOpMgr(NFPlayer* pPlayer, int iOpReson, bool bNeedCommit) : NFBagPageOpMgrInterface(pPlayer->GetRoleID(), iOpReson, bNeedCommit), m_pPlayer(pPlayer), m_moneyOp(pPlayer, iOpReson, bNeedCommit)
{

}

NFBagPageOpMgr::~NFBagPageOpMgr()
{
}

int NFBagPageOpMgr::Commit(bool bSyncToClient)
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    iRetCode = CommitToPlayer();
    CHECK_ERR(m_pPlayer->GetRoleID(), iRetCode, "Commit");

    if (bSyncToClient)
    {
        iRetCode = SyncToPlayer();
        CHECK_ERR_NT(m_pPlayer->GetRoleID(), iRetCode, "SyncToPlayer");
    }

    // 进行预缴操作
    iRetCode = Disgorgment();
    CHECK_ERR_NT(m_pPlayer->GetRoleID(), iRetCode, "Disgorgment");

    return 0;
}

int NFBagPageOpMgr::CommitToPlayer()
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    iRetCode = PreCheckCommit();
    CHECK_ERR(m_pPlayer->GetRoleID(), iRetCode, "PreCheckCommit");

    m_moneyOp.BaseCommit();

    iRetCode = m_moneyOp.Commit(false, true);
    CHECK_ERR(m_pPlayer->GetRoleID(), iRetCode, "m_MoneyOp.Commit");
    // 货币更改已经提交了，之后不允许有失败返回逻辑
    m_pPlayer->MarkDirty();

    m_opItemRec.clear();
    for (int i = 0; i < (int)m_allBagPageOps.size(); i++)
    {
        NFBagPageOp* pBagPageOp = m_allBagPageOps[i];
        if (pBagPageOp)
        {
            pBagPageOp->Commit(m_opItemRec);
        }
    }

    BaseCommit();
    m_pPlayer->MarkDirty();

    proto_ff::EventPlayerItemAdd addEvent;
    addEvent.set_reason(m_enPackageOpReason);
    addEvent.set_from_mail(m_bFromMail);

    proto_ff::EventPlayerItemDel delEvent;
    delEvent.set_reason(m_enPackageOpReason);

    for (auto iter = m_opItemRec.begin(); iter != m_opItemRec.end(); ++iter)
    {
        LOG_TRACE(m_pPlayer->GetRoleID(), "itemId:{} num:{}", iter->first, iter->second);
        if (iter->second > 0)
        {
            m_itemChangeRec[iter->first] = iter->second;
            addEvent.set_item_id(iter->first);
            addEvent.set_num(iter->second);
            FindModule<NFIEventModule>()->FireExecute(NF_ST_LOGIC_SERVER, EVENT_PLAYER_ITEM_ADD, EVENT_SRC_TYPE_PLAYER, m_pPlayer->GetRoleID(), addEvent);
        }
        else if (iter->second < 0)
        {
            m_itemChangeRec[iter->first] = iter->second;
            delEvent.set_item_id(iter->first);
            delEvent.set_num(iter->second);
            FindModule<NFIEventModule>()->FireExecute(NF_ST_LOGIC_SERVER, EVENT_PLAYER_ITEM_DEL, EVENT_SRC_TYPE_PLAYER, m_pPlayer->GetRoleID(), delEvent);
        }
    }
    return 0;
}

int NFBagPageOpMgr::SendRewardNtf(bool notShow, int type, int iParam)
{
    CHECK_NULL(0, m_pPlayer);
    proto_ff::Proto_CSRsp stRsp;
    proto_ff::Proto_CSRewardNtf* pstRewardNtf = stRsp.mutable_reward_ntf();
    FillPackageInfoForAdd(pstRewardNtf->mutable_item());
    pstRewardNtf->mutable_item()->set_not_show(notShow);
    pstRewardNtf->set_type(type);
    pstRewardNtf->set_reward_param_1 (iParam);
    NFPacketSendUtil::SendToClient(m_pPlayer, proto_ff::E_CS_REWARD_NTF, &stRsp);
    return 0;
}

int NFBagPageOpMgr::FillPackageInfoForAdd(proto_ff::Proto_CSRoleItemNtf* pNtf)
{
    for (int i = 0; i < (int)m_allBagPageOps.size(); i++)
    {
        NFBagPageOp* pBagPageOp = m_allBagPageOps[i];
        if (pBagPageOp)
        {
            pBagPageOp->FillPackageInfoForAdd(pNtf, m_enPackageOpReason);
        }
    }
    m_moneyOp.FillPackageInfoForAdd(pNtf);
    return 0;
}

int NFBagPageOpMgr::FillPackageInfoForDel(proto_ff::Proto_CSRoleItemNtf* pNtf)
{
    for (int i = 0; i < (int)m_allBagPageOps.size(); i++)
    {
        NFBagPageOp* pBagPageOp = m_allBagPageOps[i];
        if (pBagPageOp)
        {
            pBagPageOp->FillPackageInfoForDel(pNtf, m_enPackageOpReason);
        }
    }
    m_moneyOp.FillPackageInfoForDel(pNtf);
    return 0;
}

int NFBagPageOpMgr::SyncToPlayer()
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    iRetCode = SyncPackageToPlayer(m_pPlayer);
    CHECK_ERR_NT(m_pPlayer->GetRoleID(), iRetCode, "SyncPackageToPlayer");

    iRetCode = m_moneyOp.SyncToClient();
    CHECK_ERR_NT(m_pPlayer->GetRoleID(), iRetCode, "m_MoneyOp.SyncToClient");

    return 0;
}

int NFBagPageOpMgr::PreCheckCommit()
{
    int iRetCode = 0;
    iRetCode = BaseCommitCheck();
    CHECK_ERR(m_ownerId, iRetCode, "BaseCommitCheck");

    iRetCode = m_moneyOp.PreCheckCommit(false);
    CHECK_ERR(m_ownerId, iRetCode, "m_moneyOp.CommitCheck");

    for (int i = 0; i < (int)m_allBagPageOps.size(); i++)
    {
        NFBagPageOp* pBagPageOp = m_allBagPageOps[i];
        if (pBagPageOp)
        {
            iRetCode = pBagPageOp->PreCheckCommit();
            CHECK_ERR(m_ownerId, iRetCode, "pBagPageOp->PreCheckCommit");
        }
    }
    return 0;
}

int NFBagPageOpMgr::SyncPackageToPlayer(NFPlayer* pPlayer)
{
    proto_ff::Proto_CSRsp respond;
    proto_ff::Proto_CSRoleItemNtf* pNtf = respond.mutable_role_item_ntf();
    for (int i = 0; i < (int)m_allBagPageOps.size(); i++)
    {
        NFBagPageOp* pBagPageOp = m_allBagPageOps[i];
        if (pBagPageOp)
        {
            pBagPageOp->FillPackageInfoNotify(pNtf, GetPackageOpReason());
        }
    }

    NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_ROLE_ITEM_NTF, &respond);
    return 0;
}

NFBagPage* NFBagPageOpMgr::GetBagPage(int iBagType)
{
    CHECK_NULL_RE_NULL(0, m_pPlayer, "");
    NFPackagePart* pPackage = m_pPlayer->GetPart<NFPackagePart>(PART_PACKAGE);
    CHECK_NULL_RE_NULL(m_pPlayer->GetRoleID(), pPackage, "");

    NFBagPage *pBagPage = pPackage->GetPageByType(iBagType);
    CHECK_NULL_RE_NULL(m_pPlayer->GetRoleID(), pBagPage, "GetPageByType Failed iBagType:%d", iBagType);

    return pBagPage;
}

int NFBagPageOpMgr::AddAllBagPage()
{
    int iRetCode = 0;
    CHECK_NULL(0, m_pPlayer);

    iRetCode = AddBagPageOp(g_personAllOpBagType);
    CHECK_ERR(m_pPlayer->GetRoleID(), iRetCode, "AddBagPageOp");
    return 0;
}

int64_t NFBagPageOpMgr::GetMoneyNumber(int moneyType)
{
    return NFServicePackage::GetMoneyNumber(m_pPlayer, moneyType);
}

int NFBagPageOpMgr::SetMoneyNumber(int moneyType, int64_t num)
{
    return NFServicePackage::SetMoneyNumber(m_pPlayer, moneyType, num);
}

int NFBagPageOpMgr::IncMoney(int enMoneyType, int llMoney, int* pAddedNum)
{
    int64_t ullAddedNum = 0;
    int iRetCode = m_moneyOp.Inc(enMoneyType, llMoney, &ullAddedNum);
    CHECK_ERR(m_ownerId, iRetCode, "m_MoneyOp.In, moneyType:{} iNum:{}", enMoneyType, llMoney);
    if (pAddedNum)
    {
        *pAddedNum = ullAddedNum;
    }
    return 0;
}

int NFBagPageOpMgr::DecMoney(int enMoneyType, int llMoney, int* piDelNum)
{
    int64_t pllDelNum = 0;
    int iRetCode = m_moneyOp.Dec(enMoneyType, llMoney, &pllDelNum);
    CHECK_ERR(m_ownerId, iRetCode, "m_MoneyOp.Dec, moneyType:{} iNum:{}", enMoneyType, llMoney);
    if (piDelNum)
    {
        *piDelNum = pllDelNum;
    }
    return 0;
}

int NFBagPageOpMgr::AddItemWhenBagFull(const WillAddItemData& stWillAddItemData, int iLeftAddNum, int& iAddNum)
{
    int iRetCode = 0;
    NFBagPageOp* pBagPageOp = GetBagPageOpByBagType(EN_BPT_TEMP_STORAGE);
    CHECK_NULL(m_ownerId, pBagPageOp);

    iRetCode = pBagPageOp->AddItem(stWillAddItemData, iLeftAddNum, iAddNum);
    CHECK_ERR(m_ownerId, iRetCode, "pOpContainer->AddWares");

    return 0;
}

int NFBagPageOpMgr::AddItemWhenBagFull(const NFGridItem* pItem, int iLeftAddNum, int& iAddNum)
{
    CHECK_NULL(m_ownerId, pItem);
    int iRetCode = 0;
    NFBagPageOp* pBagPageOp = GetBagPageOpByBagType(EN_BPT_TEMP_STORAGE);
    CHECK_NULL(m_ownerId, pBagPageOp);

    iRetCode = pBagPageOp->AddItem(pItem, iLeftAddNum, iAddNum);
    CHECK_ERR(m_ownerId, iRetCode, "pOpContainer->AddWares");

    return 0;
}

